/***************************************************************************
 *   Copyright (C) 2010 by Oleg Goncharov  *
 *   $EMAIL$                           *                          
 *                                                                         *
 *   This file is part of ChessVision.                                     *
 *                                                                         *
 *   ChessVision is free software; you can redistribute it and/or modify   *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <opencv/cv.h>

#include "cpointmatch.h"

CPointMatch::CPointMatch(const Mat & _sample, NormMode _mode) : CPointNorm(_mode) 
{
    Normalize(_sample, sample);
    // large value ... TODO Add meaningfull comment
    threshold = sample.rows*sample.cols;
    threshold *= threshold;
}

CPointMatch::~CPointMatch() 
{
}

bool CPointMatch::DetectPoint(const Mat& img, Point2f& point) // TODO Test
{
    Mat	diff(img.cols - sample.cols + 1, img.rows - sample.rows + 1, img.type());
    Mat	src;
    
    Normalize(img, src);
    
    Point min_loc;
    double min, max;

    matchTemplate(src, sample, diff, CV_TM_SQDIFF);
    minMaxLoc(diff,  &min, &max, &min_loc);

    point.x = min_loc.x + sample.cols*0.5;
    point.y = min_loc.y + sample.rows*0.5;

    return (min <= threshold);
}


CPointScaleMatch::CPointScaleMatch(const Mat& _sample, float min_scale, 
				   float max_scale, int nsteps, NormMode _mode) : CPointNorm(_mode) 
{
    float scale, sstep = fabs(min_scale - max_scale)/nsteps;
    int i;
    Size size;
    //CvSize size;
    Mat sample;
    Normalize(_sample, sample);
    //IplImage * sample = Normalize(_sample);
    // TODO what does this mean?
    threshold = sample.rows*sample.cols;
    threshold *= threshold;
    
    nsamples = nsteps + 1;

    samples = new Mat[nsamples];
    areas = new int[nsamples];

    //cvShowImage("win", sample); cvWaitKey(0);

    for (scale = min_scale, i = 0; i < nsamples; i++, scale +=  sstep) 
    {
        size = Size(cvRound(scale*sample.cols), cvRound(scale*sample.rows));
	resize(sample, samples[i], size);
        areas[i] = size.height*size.width;
    }
}

bool CPointScaleMatch::DetectPoint(const Mat& img, Point2f& point) 
{
    Mat diff(img.size(), CV_32FC1), src;
    Normalize(img, src);
    Point min_loc;
    double min, max, best = 1e100;

    //cvShowImage("win", src); cvWaitKey(0);

    for (int i = 0; i < nsamples; i++) 
    {
	Mat roi_diff = diff( Rect(0, 0, img.cols - samples[i].cols + 1, img.rows - samples[i].rows + 1) );
	
	matchTemplate( src, samples[i], roi_diff, CV_TM_SQDIFF );
	minMaxLoc(roi_diff, &min, &max, &min_loc);
        min /= areas[i];
        if (min < best) 
	{
            best = min;
            point.x = min_loc.x + samples[i].cols*0.5;
            point.y = min_loc.y + samples[i].rows*0.5;
        }
    }
  
    return (min <= threshold);
}

CPointScaleMatch::~CPointScaleMatch() 
{
    delete [] samples;
    delete [] areas;
}



